Validate AST before creating new item (#3754)
This commit is contained in:
parent
34c00e7dbd
commit
4653c34fd5
@ -1407,6 +1407,22 @@ class DynamoDBBackend(BaseBackend):
|
||||
|
||||
# Update does not fail on new items, so create one
|
||||
if item is None:
|
||||
if update_expression:
|
||||
# Validate AST before creating anything
|
||||
item = Item(
|
||||
hash_value,
|
||||
table.hash_key_type,
|
||||
range_value,
|
||||
table.range_key_type,
|
||||
attrs={},
|
||||
)
|
||||
UpdateExpressionValidator(
|
||||
update_expression_ast,
|
||||
expression_attribute_names=expression_attribute_names,
|
||||
expression_attribute_values=expression_attribute_values,
|
||||
item=item,
|
||||
table=table,
|
||||
).validate()
|
||||
data = {table.hash_key_attr: {hash_value.type: hash_value.value}}
|
||||
if range_value:
|
||||
data.update(
|
||||
|
@ -6245,3 +6245,35 @@ def test_describe_endpoints(region):
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@mock_dynamodb2
|
||||
def test_update_non_existing_item_raises_error_and_does_not_contain_item_afterwards():
|
||||
"""
|
||||
https://github.com/spulec/moto/issues/3729
|
||||
Exception is raised, but item was persisted anyway
|
||||
Happened because we would create a placeholder, before validating/executing the UpdateExpression
|
||||
:return:
|
||||
"""
|
||||
name = "TestTable"
|
||||
conn = boto3.client("dynamodb", region_name="us-west-2")
|
||||
hkey = "primary_partition_key"
|
||||
conn.create_table(
|
||||
TableName=name,
|
||||
KeySchema=[{"AttributeName": hkey, "KeyType": "HASH"}],
|
||||
AttributeDefinitions=[{"AttributeName": hkey, "AttributeType": "S"}],
|
||||
ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5},
|
||||
)
|
||||
update_expression = {
|
||||
"Key": {hkey: "some_identification_string"},
|
||||
"UpdateExpression": "set #AA.#AB = :aa",
|
||||
"ExpressionAttributeValues": {":aa": "abc"},
|
||||
"ExpressionAttributeNames": {"#AA": "some_dict", "#AB": "key1"},
|
||||
"ConditionExpression": "attribute_not_exists(#AA.#AB)",
|
||||
}
|
||||
table = boto3.resource("dynamodb", region_name="us-west-2").Table(name)
|
||||
with pytest.raises(ClientError) as err:
|
||||
table.update_item(**update_expression)
|
||||
err.value.response["Error"]["Code"].should.equal("ValidationException")
|
||||
|
||||
conn.scan(TableName=name)["Items"].should.have.length_of(0)
|
||||
|
Loading…
Reference in New Issue
Block a user