DynamoDB: FilterExpressions/ProjectionExpressions cannot be an empty string (#6636)
This commit is contained in:
parent
4179de8a61
commit
f297c4216f
@ -316,7 +316,7 @@ class DynamoDBBackend(BaseBackend):
|
||||
limit: int,
|
||||
exclusive_start_key: Dict[str, Any],
|
||||
scan_index_forward: bool,
|
||||
projection_expression: str,
|
||||
projection_expression: Optional[str],
|
||||
index_name: Optional[str] = None,
|
||||
expr_names: Optional[Dict[str, str]] = None,
|
||||
expr_values: Optional[Dict[str, str]] = None,
|
||||
@ -351,11 +351,11 @@ class DynamoDBBackend(BaseBackend):
|
||||
filters: Dict[str, Any],
|
||||
limit: int,
|
||||
exclusive_start_key: Dict[str, Any],
|
||||
filter_expression: str,
|
||||
filter_expression: Optional[str],
|
||||
expr_names: Dict[str, Any],
|
||||
expr_values: Dict[str, Any],
|
||||
index_name: str,
|
||||
projection_expression: str,
|
||||
projection_expression: Optional[str],
|
||||
) -> Tuple[List[Item], int, Optional[Dict[str, Any]]]:
|
||||
table = self.get_table(table_name)
|
||||
|
||||
|
@ -637,7 +637,7 @@ class Table(CloudFormationModel):
|
||||
limit: int,
|
||||
exclusive_start_key: Dict[str, Any],
|
||||
scan_index_forward: bool,
|
||||
projection_expression: str,
|
||||
projection_expression: Optional[str],
|
||||
index_name: Optional[str] = None,
|
||||
filter_expression: Any = None,
|
||||
**filter_kwargs: Any,
|
||||
|
@ -351,6 +351,22 @@ class DynamoHandler(BaseResponse):
|
||||
+ dump_list(actual_attrs)
|
||||
)
|
||||
|
||||
def _get_filter_expression(self) -> Optional[str]:
|
||||
filter_expression = self.body.get("FilterExpression")
|
||||
if filter_expression == "":
|
||||
raise MockValidationException(
|
||||
"Invalid FilterExpression: The expression can not be empty;"
|
||||
)
|
||||
return filter_expression
|
||||
|
||||
def _get_projection_expression(self) -> Optional[str]:
|
||||
expression = self.body.get("ProjectionExpression")
|
||||
if expression == "":
|
||||
raise MockValidationException(
|
||||
"Invalid ProjectionExpression: The expression can not be empty;"
|
||||
)
|
||||
return expression
|
||||
|
||||
def delete_table(self) -> str:
|
||||
name = self.body["TableName"]
|
||||
table = self.dynamodb_backend.delete_table(name)
|
||||
@ -521,7 +537,7 @@ class DynamoHandler(BaseResponse):
|
||||
f"empty string value. Key: {empty_keys[0]}"
|
||||
)
|
||||
|
||||
projection_expression = self.body.get("ProjectionExpression")
|
||||
projection_expression = self._get_projection_expression()
|
||||
attributes_to_get = self.body.get("AttributesToGet")
|
||||
if projection_expression and attributes_to_get:
|
||||
raise MockValidationException(
|
||||
@ -631,9 +647,9 @@ class DynamoHandler(BaseResponse):
|
||||
def query(self) -> str:
|
||||
name = self.body["TableName"]
|
||||
key_condition_expression = self.body.get("KeyConditionExpression")
|
||||
projection_expression = self.body.get("ProjectionExpression")
|
||||
projection_expression = self._get_projection_expression()
|
||||
expression_attribute_names = self.body.get("ExpressionAttributeNames", {})
|
||||
filter_expression = self.body.get("FilterExpression")
|
||||
filter_expression = self._get_filter_expression()
|
||||
expression_attribute_values = self.body.get("ExpressionAttributeValues", {})
|
||||
|
||||
projection_expression = self._adjust_projection_expression(
|
||||
@ -726,8 +742,8 @@ class DynamoHandler(BaseResponse):
|
||||
return dynamo_json_dump(result)
|
||||
|
||||
def _adjust_projection_expression(
|
||||
self, projection_expression: str, expr_attr_names: Dict[str, str]
|
||||
) -> str:
|
||||
self, projection_expression: Optional[str], expr_attr_names: Dict[str, str]
|
||||
) -> Optional[str]:
|
||||
def _adjust(expression: str) -> str:
|
||||
return (
|
||||
expr_attr_names[expression]
|
||||
@ -762,10 +778,10 @@ class DynamoHandler(BaseResponse):
|
||||
comparison_values = scan_filter.get("AttributeValueList", [])
|
||||
filters[attribute_name] = (comparison_operator, comparison_values)
|
||||
|
||||
filter_expression = self.body.get("FilterExpression")
|
||||
filter_expression = self._get_filter_expression()
|
||||
expression_attribute_values = self.body.get("ExpressionAttributeValues", {})
|
||||
expression_attribute_names = self.body.get("ExpressionAttributeNames", {})
|
||||
projection_expression = self.body.get("ProjectionExpression", "")
|
||||
projection_expression = self._get_projection_expression()
|
||||
exclusive_start_key = self.body.get("ExclusiveStartKey")
|
||||
limit = self.body.get("Limit")
|
||||
index_name = self.body.get("IndexName")
|
||||
|
@ -144,7 +144,7 @@ def test_empty_expressionattributenames_with_empty_projection():
|
||||
table = ddb.Table("test-table")
|
||||
with pytest.raises(ClientError) as exc:
|
||||
table.get_item(
|
||||
Key={"id": "my_id"}, ProjectionExpression="", ExpressionAttributeNames={}
|
||||
Key={"id": "my_id"}, ProjectionExpression="a", ExpressionAttributeNames={}
|
||||
)
|
||||
err = exc.value.response["Error"]
|
||||
assert err["Code"] == "ValidationException"
|
||||
@ -1067,3 +1067,30 @@ def test_list_append_errors_for_unknown_attribute_value():
|
||||
ExpressionAttributeValues={":i": {"L": [{"S": "bar2"}]}},
|
||||
ReturnValues="UPDATED_NEW",
|
||||
)
|
||||
|
||||
|
||||
@mock_dynamodb
|
||||
def test_query_with_empty_filter_expression():
|
||||
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.query(
|
||||
KeyConditionExpression="partitionKey = sth", ProjectionExpression=""
|
||||
)
|
||||
err = exc.value.response["Error"]
|
||||
assert err["Code"] == "ValidationException"
|
||||
assert (
|
||||
err["Message"]
|
||||
== "Invalid ProjectionExpression: The expression can not be empty;"
|
||||
)
|
||||
|
||||
with pytest.raises(ClientError) as exc:
|
||||
table.query(KeyConditionExpression="partitionKey = sth", FilterExpression="")
|
||||
err = exc.value.response["Error"]
|
||||
assert err["Code"] == "ValidationException"
|
||||
assert (
|
||||
err["Message"] == "Invalid FilterExpression: The expression can not be empty;"
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user