From 08da2c92d92defbcc5390abb3e831a09a17b2e82 Mon Sep 17 00:00:00 2001 From: Sarang Joshi Date: Mon, 5 Oct 2020 08:40:33 -0400 Subject: [PATCH] fix(dynamodb2): Fix update_item nested insert (#3355) When comparing old and new values when doing a nested item update, the `!=` implementation fails when the value being compared is `None`. This results in an exception when trying to insert a new item into a nested map. So just do a quick check that the original value is exists before doing the comparison, as the `None` default is what is tripping this. --- moto/dynamodb2/responses.py | 2 +- tests/test_dynamodb2/test_dynamodb.py | 31 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/moto/dynamodb2/responses.py b/moto/dynamodb2/responses.py index 2b252af15..25ec29238 100644 --- a/moto/dynamodb2/responses.py +++ b/moto/dynamodb2/responses.py @@ -826,7 +826,7 @@ class DynamoHandler(BaseResponse): original.get(key, None), changed[key] ) for key in changed.keys() - if changed[key] != original.get(key, None) + if key not in original or changed[key] != original[key] } elif type(changed) in (set, list): if len(changed) != len(original): diff --git a/tests/test_dynamodb2/test_dynamodb.py b/tests/test_dynamodb2/test_dynamodb.py index d56fd3f11..e2dd744e3 100644 --- a/tests/test_dynamodb2/test_dynamodb.py +++ b/tests/test_dynamodb2/test_dynamodb.py @@ -3936,6 +3936,37 @@ def test_update_supports_list_append_maps(): ) +@requires_boto_gte("2.9") +@mock_dynamodb2 +def test_update_supports_nested_update_if_nested_value_not_exists(): + dynamodb = boto3.resource("dynamodb", region_name="us-east-1") + name = "TestTable" + + dynamodb.create_table( + TableName=name, + KeySchema=[{"AttributeName": "user_id", "KeyType": "HASH"}], + AttributeDefinitions=[{"AttributeName": "user_id", "AttributeType": "S"}], + ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, + ) + + table = dynamodb.Table(name) + table.put_item( + Item={"user_id": "1234", "friends": {"5678": {"name": "friend_5678"}},}, + ) + table.update_item( + Key={"user_id": "1234"}, + ExpressionAttributeNames={"#friends": "friends", "#friendid": "0000",}, + ExpressionAttributeValues={":friend": {"name": "friend_0000"},}, + UpdateExpression="SET #friends.#friendid = :friend", + ReturnValues="UPDATED_NEW", + ) + item = table.get_item(Key={"user_id": "1234"})["Item"] + assert item == { + "user_id": "1234", + "friends": {"5678": {"name": "friend_5678"}, "0000": {"name": "friend_0000"},}, + } + + @mock_dynamodb2 def test_update_supports_list_append_with_nested_if_not_exists_operation(): dynamo = boto3.resource("dynamodb", region_name="us-west-1")