Skip to content

Commit

Permalink
DynamoDB: transact_write_items() now validates empty ExpressionAttrib…
Browse files Browse the repository at this point in the history
…uteValues (#8443)
  • Loading branch information
bblommers authored Dec 30, 2024
1 parent 289d76b commit 50e7bde
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 1 deletion.
5 changes: 5 additions & 0 deletions moto/dynamodb/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ def __init__(self, attribute_value: str):
)


class ExpressionAttributeValuesEmpty(MockValidationException):
def __init__(self) -> None:
super().__init__("ExpressionAttributeValues must not be empty")


class UpdateExprSyntaxError(InvalidUpdateExpression):
update_expr_syntax_error_msg = "Syntax error; {error_detail}"

Expand Down
9 changes: 8 additions & 1 deletion moto/dynamodb/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from moto.utilities.aws_headers import amz_crc32

from .exceptions import (
ExpressionAttributeValuesEmpty,
InvalidProjectionExpression,
KeyIsEmptyStringException,
MockValidationException,
Expand Down Expand Up @@ -1012,7 +1013,7 @@ def _get_expr_attr_values(self) -> Dict[str, Dict[str, str]]:
if values is None:
return {}
if len(values) == 0:
raise MockValidationException("ExpressionAttributeValues must not be empty")
raise ExpressionAttributeValuesEmpty
for key in values.keys():
if not key.startswith(":"):
raise MockValidationException(
Expand Down Expand Up @@ -1134,10 +1135,16 @@ def transact_write_items(self) -> str:
# Validate first - we should error before we start the transaction
for item in transact_items:
if "Put" in item:
if item["Put"].get("ExpressionAttributeValues") == {}:
raise ExpressionAttributeValuesEmpty

item_attrs = item["Put"]["Item"]
table = self.dynamodb_backend.get_table(item["Put"]["TableName"])
validate_put_has_empty_keys(item_attrs, table)
if "Update" in item:
if item["Update"].get("ExpressionAttributeValues") == {}:
raise ExpressionAttributeValuesEmpty

item_attrs = item["Update"]["Key"]
table = self.dynamodb_backend.get_table(item["Update"]["TableName"])
validate_put_has_empty_keys(
Expand Down
42 changes: 42 additions & 0 deletions tests/test_dynamodb/exceptions/test_dynamodb_transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,3 +273,45 @@ def test_transaction_with_empty_key(table_name=None):
err["Message"]
== "One or more parameter values are not valid. The AttributeValue for a key attribute cannot contain an empty string value. Key: pk"
)


@pytest.mark.aws_verified
@dynamodb_aws_verified()
def test_transact_write_items__empty_expr_attr_values(table_name=None):
dynamodb = boto3.client("dynamodb", region_name="us-east-1")

with pytest.raises(ClientError) as exc:
dynamodb.transact_write_items(
TransactItems=[
{
"Put": {
"Item": {"pk": {"S": "tenant#0000001-tenant#0000001"}},
"ConditionExpression": "attribute_not_exists(#n0)",
"TableName": table_name,
"ExpressionAttributeNames": {"#n0": "pk"},
"ExpressionAttributeValues": {},
}
},
]
)
err = exc.value.response["Error"]
assert err["Code"] == "ValidationException"
assert err["Message"] == "ExpressionAttributeValues must not be empty"

with pytest.raises(ClientError) as exc:
dynamodb.transact_write_items(
TransactItems=[
{
"Update": {
"Key": {"pk": {"S": "globals"}},
"UpdateExpression": "SET #0 = {'S': 'asdf'}",
"ExpressionAttributeNames": {"#0": "tenant_count"},
"ExpressionAttributeValues": {},
"TableName": table_name,
}
},
]
)
err = exc.value.response["Error"]
assert err["Code"] == "ValidationException"
assert err["Message"] == "ExpressionAttributeValues must not be empty"

0 comments on commit 50e7bde

Please sign in to comment.