From 44310b5e0eb871461583eefcb27c62160713b98d Mon Sep 17 00:00:00 2001 From: Bert Blommers Date: Sat, 11 May 2024 20:09:14 +0000 Subject: [PATCH] DynamoDB: update_item() now throws the appriopriate exception when adding an empty set (#7684) --- moto/dynamodb/parsing/executors.py | 5 ++ .../test_dynamodb_update_expressions.py | 47 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/moto/dynamodb/parsing/executors.py b/moto/dynamodb/parsing/executors.py index b6a7c6eeff70..23aac7d6d9e1 100644 --- a/moto/dynamodb/parsing/executors.py +++ b/moto/dynamodb/parsing/executors.py @@ -4,6 +4,7 @@ from moto.dynamodb.exceptions import ( IncorrectDataType, IncorrectOperandType, + MockValidationException, ProvidedKeyDoesNotExist, ) from moto.dynamodb.models.dynamo_type import ( @@ -226,6 +227,10 @@ def execute(self, item: Item) -> None: value_to_add = self.get_action_value() if isinstance(value_to_add, DynamoType): if value_to_add.is_set(): + if len(value_to_add.value) == 0: + raise MockValidationException( + "ExpressionAttributeValues contains invalid value: One or more parameter values were invalid: An string set may not be empty" + ) try: current_string_set = self.get_item_at_end_of_path(item) except ProvidedKeyDoesNotExist: diff --git a/tests/test_dynamodb/test_dynamodb_update_expressions.py b/tests/test_dynamodb/test_dynamodb_update_expressions.py index d891f75d842d..5115e7168261 100644 --- a/tests/test_dynamodb/test_dynamodb_update_expressions.py +++ b/tests/test_dynamodb/test_dynamodb_update_expressions.py @@ -2,6 +2,7 @@ import boto3 import pytest +from botocore.exceptions import ClientError from . import dynamodb_aws_verified @@ -140,3 +141,49 @@ def test_delete_non_existing_item(table_name=None): ReturnValues="ALL_NEW", ) assert table.get_item(Key={"pk": name})["Item"] == {"pk": "name"} + + +@pytest.mark.aws_verified +@dynamodb_aws_verified() +def test_update_item_add_empty_set(table_name=None): + dynamodb = boto3.client("dynamodb", "us-east-1") + + # Add to non-existing attribute + dynamodb.put_item(TableName=table_name, Item={"pk": {"S": "foo"}}) + with pytest.raises(ClientError) as exc: + dynamodb.update_item( + TableName=table_name, + Key={"pk": {"S": "foo"}}, + UpdateExpression="ADD stringset :emptySet", + ExpressionAttributeValues={":emptySet": {"SS": ()}}, + ) + err = exc.value.response["Error"] + assert err["Code"] == "ValidationException" + assert ( + err["Message"] + == "ExpressionAttributeValues contains invalid value: One or more parameter values were invalid: An string set may not be empty" + ) + + assert dynamodb.scan(TableName=table_name)["Items"] == [{"pk": {"S": "foo"}}] + + # Still not allowed when the attribute exists + dynamodb.put_item( + TableName=table_name, Item={"pk": {"S": "foo"}, "stringset": {"SS": ("item1",)}} + ) + with pytest.raises(ClientError) as exc: + dynamodb.update_item( + TableName=table_name, + Key={"pk": {"S": "foo"}}, + UpdateExpression="ADD stringset :emptySet", + ExpressionAttributeValues={":emptySet": {"SS": ()}}, + ) + err = exc.value.response["Error"] + assert err["Code"] == "ValidationException" + assert ( + err["Message"] + == "ExpressionAttributeValues contains invalid value: One or more parameter values were invalid: An string set may not be empty" + ) + + assert dynamodb.scan(TableName=table_name)["Items"] == [ + {"pk": {"S": "foo"}, "stringset": {"SS": ["item1"]}} + ]