From 69888c3baa67a5cedd3f339c94472fbaaaa750a3 Mon Sep 17 00:00:00 2001 From: Victor Blaga Date: Tue, 21 Jun 2016 17:45:22 +0200 Subject: [PATCH 1/2] update_item takes into account ExpressionAttributeNames and ExpressionAttributeValues ExpressionAttributeNames and ExpressionAttributeValues are no longer ignored during update_item. --- moto/dynamodb2/models.py | 23 +++++++++++++---------- moto/dynamodb2/responses.py | 4 +++- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/moto/dynamodb2/models.py b/moto/dynamodb2/models.py index 095dc06cc..02201be2d 100644 --- a/moto/dynamodb2/models.py +++ b/moto/dynamodb2/models.py @@ -109,8 +109,8 @@ class Item(object): "Item": included } - def update(self, update_expression): - ACTION_VALUES = ['SET', 'REMOVE'] + def update(self, update_expression, expression_attribute_names, expression_attribute_values): + ACTION_VALUES = ['SET', 'set', 'REMOVE', 'remove'] action = None for value in update_expression.split(): @@ -121,13 +121,16 @@ class Item(object): else: # A Real value value = value.lstrip(":").rstrip(",") - - if action == "REMOVE": + for k, v in expression_attribute_names.items(): + value = value.replace(k, v) + if action == "REMOVE" or action == 'remove': self.attrs.pop(value, None) - elif action == 'SET': - key, value = value.split("=:") - # TODO deal with other types - self.attrs[key] = DynamoType({"S": value}) + elif action == 'SET' or action == 'set': + key, value = value.split("=") + if value in expression_attribute_values: + self.attrs[key] = DynamoType(expression_attribute_values[value]) + else: + self.attrs[key] = DynamoType({"S": value}) def update_with_attribute_updates(self, attribute_updates): for attribute_name, update_action in attribute_updates.items(): @@ -583,7 +586,7 @@ class DynamoDBBackend(BaseBackend): return table.scan(scan_filters, limit, exclusive_start_key) - def update_item(self, table_name, key, update_expression, attribute_updates): + def update_item(self, table_name, key, update_expression, attribute_updates, expression_attribute_names, expression_attribute_values): table = self.get_table(table_name) if all([table.hash_key_attr in key, table.range_key_attr in key]): @@ -618,7 +621,7 @@ class DynamoDBBackend(BaseBackend): item = table.get_item(hash_value, range_value) if update_expression: - item.update(update_expression) + item.update(update_expression, expression_attribute_names, expression_attribute_values) else: item.update_with_attribute_updates(attribute_updates) return item diff --git a/moto/dynamodb2/responses.py b/moto/dynamodb2/responses.py index 4c0265449..76bba9e49 100644 --- a/moto/dynamodb2/responses.py +++ b/moto/dynamodb2/responses.py @@ -395,8 +395,10 @@ class DynamoHandler(BaseResponse): key = self.body['Key'] update_expression = self.body.get('UpdateExpression') attribute_updates = self.body.get('AttributeUpdates') + expression_attribute_names = self.body.get('ExpressionAttributeNames', {}) + expression_attribute_values = self.body.get('ExpressionAttributeValues', {}) existing_item = dynamodb_backend2.get_item(name, key) - item = dynamodb_backend2.update_item(name, key, update_expression, attribute_updates) + item = dynamodb_backend2.update_item(name, key, update_expression, attribute_updates, expression_attribute_names, expression_attribute_values) item_dict = item.to_json() item_dict['ConsumedCapacityUnits'] = 0.5 From cb36a8b10fa58710c88ca441e91a7923472b94c0 Mon Sep 17 00:00:00 2001 From: Victor Blaga Date: Tue, 21 Jun 2016 17:46:37 +0200 Subject: [PATCH 2/2] Fix dynamodb_v2 update_item tests Update expression has the wrong syntax. Something like :bar denotes a placeholder which has to be filled by supplying an additional ExpressionAttributeNames --- tests/test_dynamodb2/test_dynamodb_table_without_range_key.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_dynamodb2/test_dynamodb_table_without_range_key.py b/tests/test_dynamodb2/test_dynamodb_table_without_range_key.py index c17d66834..5a32c6b20 100644 --- a/tests/test_dynamodb2/test_dynamodb_table_without_range_key.py +++ b/tests/test_dynamodb2/test_dynamodb_table_without_range_key.py @@ -435,7 +435,7 @@ def test_update_item_remove(): } # Then remove the SentBy field - conn.update_item("messages", key_map, update_expression="REMOVE :SentBy, :SentTo") + conn.update_item("messages", key_map, update_expression="REMOVE SentBy, SentTo") returned_item = table.get_item(username="steve") dict(returned_item).should.equal({ @@ -459,7 +459,7 @@ def test_update_item_set(): 'username': {"S": "steve"} } - conn.update_item("messages", key_map, update_expression="SET foo=:bar, blah=:baz REMOVE :SentBy") + conn.update_item("messages", key_map, update_expression="SET foo=bar, blah=baz REMOVE SentBy") returned_item = table.get_item(username="steve") dict(returned_item).should.equal({