From bdd4ae824b9dcf954352c190c7a770208105e07b Mon Sep 17 00:00:00 2001 From: Paul Craciunoiu Date: Thu, 14 Jan 2016 15:44:28 -0700 Subject: [PATCH] Support ADD for numeric values --- moto/dynamodb2/models.py | 11 ++++ .../test_dynamodb_table_with_range_key.py | 54 +++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/moto/dynamodb2/models.py b/moto/dynamodb2/models.py index 950b0cf1d..20e6f7b33 100644 --- a/moto/dynamodb2/models.py +++ b/moto/dynamodb2/models.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals from collections import defaultdict import datetime +import decimal import json from moto.compat import OrderedDict @@ -142,6 +143,16 @@ class Item(object): del self.attrs[attribute_name] else: self.attrs[attribute_name] = DynamoType({"S": new_value}) + elif action == 'ADD': + if set(update_action['Value'].keys()) == set(['N']): + existing = self.attrs.get(attribute_name, DynamoType({"N": '0'})) + self.attrs[attribute_name] = DynamoType({"N": str( + decimal.Decimal(existing.value) + + decimal.Decimal(new_value) + )}) + else: + # TODO: implement other data types + raise NotImplementedError('ADD not supported for %s' % ', '.join(update_action['Value'].keys())) class Table(object): diff --git a/tests/test_dynamodb2/test_dynamodb_table_with_range_key.py b/tests/test_dynamodb2/test_dynamodb_table_with_range_key.py index 4346a85bf..6a5010bb5 100644 --- a/tests/test_dynamodb2/test_dynamodb_table_with_range_key.py +++ b/tests/test_dynamodb2/test_dynamodb_table_with_range_key.py @@ -888,6 +888,60 @@ def test_update_item_does_not_exist_is_created(): }) +@mock_dynamodb2 +def test_update_item_add_value(): + table = _create_table_with_range_key() + + table.put_item(Item={ + 'forum_name': 'the-key', + 'subject': '123', + 'numeric_field': Decimal('-1'), + }) + + item_key = {'forum_name': 'the-key', 'subject': '123'} + table.update_item( + Key=item_key, + AttributeUpdates={ + 'numeric_field': { + 'Action': u'ADD', + 'Value': Decimal('2'), + }, + }, + ) + + returned_item = dict((k, str(v) if isinstance(v, Decimal) else v) + for k, v in table.get_item(Key=item_key)['Item'].items()) + dict(returned_item).should.equal({ + 'numeric_field': '1', + 'forum_name': 'the-key', + 'subject': '123', + }) + + +@mock_dynamodb2 +def test_update_item_add_value_does_not_exist_is_created(): + table = _create_table_with_range_key() + + item_key = {'forum_name': 'the-key', 'subject': '123'} + table.update_item( + Key=item_key, + AttributeUpdates={ + 'numeric_field': { + 'Action': u'ADD', + 'Value': Decimal('2'), + }, + }, + ) + + returned_item = dict((k, str(v) if isinstance(v, Decimal) else v) + for k, v in table.get_item(Key=item_key)['Item'].items()) + dict(returned_item).should.equal({ + 'numeric_field': '2', + 'forum_name': 'the-key', + 'subject': '123', + }) + + @mock_dynamodb2 def test_boto3_query_gsi_range_comparison(): table = _create_table_with_range_key()