DynamoDB - Validate empty ExpressionAttributeNames on get_item() (#4393)

This commit is contained in:
Bert Blommers 2021-10-11 22:16:46 +00:00 committed by GitHub
parent dac33becbf
commit 476fd895b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 82 additions and 20 deletions

View File

@ -410,8 +410,19 @@ class DynamoHandler(BaseResponse):
)
key = self.body["Key"]
projection_expression = self.body.get("ProjectionExpression")
expression_attribute_names = self.body.get("ExpressionAttributeNames", {})
expression_attribute_names = self.body.get("ExpressionAttributeNames")
if expression_attribute_names == {}:
if projection_expression is None:
er = "ValidationException"
return self.error(
er,
"ExpressionAttributeNames can only be specified when using expressions",
)
else:
er = "ValidationException"
return self.error(er, "ExpressionAttributeNames must not be empty")
expression_attribute_names = expression_attribute_names or {}
projection_expression = self._adjust_projection_expression(
projection_expression, expression_attribute_names
)

View File

@ -6,27 +6,28 @@ from botocore.exceptions import ClientError
from moto import mock_dynamodb2
table_schema = {
"KeySchema": [{"AttributeName": "partitionKey", "KeyType": "HASH"}],
"GlobalSecondaryIndexes": [
{
"IndexName": "GSI-K1",
"KeySchema": [
{"AttributeName": "gsiK1PartitionKey", "KeyType": "HASH"},
{"AttributeName": "gsiK1SortKey", "KeyType": "RANGE"},
],
"Projection": {"ProjectionType": "KEYS_ONLY",},
}
],
"AttributeDefinitions": [
{"AttributeName": "partitionKey", "AttributeType": "S"},
{"AttributeName": "gsiK1PartitionKey", "AttributeType": "S"},
{"AttributeName": "gsiK1SortKey", "AttributeType": "S"},
],
}
@mock_dynamodb2
def test_query_gsi_with_wrong_key_attribute_names_throws_exception():
table_schema = {
"KeySchema": [{"AttributeName": "partitionKey", "KeyType": "HASH"}],
"GlobalSecondaryIndexes": [
{
"IndexName": "GSI-K1",
"KeySchema": [
{"AttributeName": "gsiK1PartitionKey", "KeyType": "HASH"},
{"AttributeName": "gsiK1SortKey", "KeyType": "RANGE"},
],
"Projection": {"ProjectionType": "KEYS_ONLY",},
}
],
"AttributeDefinitions": [
{"AttributeName": "partitionKey", "AttributeType": "S"},
{"AttributeName": "gsiK1PartitionKey", "AttributeType": "S"},
{"AttributeName": "gsiK1SortKey", "AttributeType": "S"},
],
}
item = {
"partitionKey": "pk-1",
"gsiK1PartitionKey": "gsi-pk",
@ -96,3 +97,53 @@ def test_query_gsi_with_wrong_key_attribute_names_throws_exception():
err["Message"].should.equal(
"Query condition missed key schema element: gsiK1SortKey"
)
@mock_dynamodb2
def test_empty_expressionattributenames():
ddb = boto3.resource("dynamodb", region_name="us-east-1")
ddb.create_table(
TableName="test-table", BillingMode="PAY_PER_REQUEST", **table_schema
)
table = ddb.Table("test-table")
with pytest.raises(ClientError) as exc:
table.get_item(
Key={"id": "my_id"}, ExpressionAttributeNames={},
)
err = exc.value.response["Error"]
err["Code"].should.equal("ValidationException")
err["Message"].should.equal(
"ExpressionAttributeNames can only be specified when using expressions"
)
@mock_dynamodb2
def test_empty_expressionattributenames_with_empty_projection():
ddb = boto3.resource("dynamodb", region_name="us-east-1")
ddb.create_table(
TableName="test-table", BillingMode="PAY_PER_REQUEST", **table_schema
)
table = ddb.Table("test-table")
with pytest.raises(ClientError) as exc:
table.get_item(
Key={"id": "my_id"}, ProjectionExpression="", ExpressionAttributeNames={},
)
err = exc.value.response["Error"]
err["Code"].should.equal("ValidationException")
err["Message"].should.equal("ExpressionAttributeNames must not be empty")
@mock_dynamodb2
def test_empty_expressionattributenames_with_projection():
ddb = boto3.resource("dynamodb", region_name="us-east-1")
ddb.create_table(
TableName="test-table", BillingMode="PAY_PER_REQUEST", **table_schema
)
table = ddb.Table("test-table")
with pytest.raises(ClientError) as exc:
table.get_item(
Key={"id": "my_id"}, ProjectionExpression="id", ExpressionAttributeNames={},
)
err = exc.value.response["Error"]
err["Code"].should.equal("ValidationException")
err["Message"].should.equal("ExpressionAttributeNames must not be empty")