DynamoDB: Query with KeyConditionExpression now throws exception on empty keys (#7065)
This commit is contained in:
parent
9e7295ddef
commit
20abb764a2
@ -19,6 +19,13 @@ class MockValidationException(DynamodbException):
|
||||
self.exception_msg = message
|
||||
|
||||
|
||||
class KeyIsEmptyStringException(MockValidationException):
|
||||
def __init__(self, empty_key: str):
|
||||
super().__init__(
|
||||
message=f"One or more parameter values are not valid. The AttributeValue for a key attribute cannot contain an empty string value. Key: {empty_key}"
|
||||
)
|
||||
|
||||
|
||||
class InvalidIndexNameError(MockValidationException):
|
||||
pass
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
from enum import Enum
|
||||
from typing import Any, List, Dict, Tuple, Optional, Union
|
||||
from moto.dynamodb.exceptions import MockValidationException
|
||||
from moto.dynamodb.exceptions import MockValidationException, KeyIsEmptyStringException
|
||||
from moto.utilities.tokenizer import GenericTokenizer
|
||||
|
||||
|
||||
@ -209,6 +209,8 @@ def validate_schema(
|
||||
)
|
||||
if comparison != "=":
|
||||
raise MockValidationException("Query key condition not supported")
|
||||
if "S" in hash_value and hash_value["S"] == "":
|
||||
raise KeyIsEmptyStringException(index_hash_key) # type: ignore[arg-type]
|
||||
|
||||
index_range_key = get_key(schema, "RANGE")
|
||||
range_key, range_comparison, range_values = next(
|
||||
@ -219,9 +221,12 @@ def validate_schema(
|
||||
),
|
||||
(None, None, []),
|
||||
)
|
||||
if index_range_key and len(results) > 1 and range_key != index_range_key:
|
||||
raise MockValidationException(
|
||||
f"Query condition missed key schema element: {index_range_key}"
|
||||
)
|
||||
if index_range_key:
|
||||
if len(results) > 1 and range_key != index_range_key:
|
||||
raise MockValidationException(
|
||||
f"Query condition missed key schema element: {index_range_key}"
|
||||
)
|
||||
if {"S": ""} in range_values:
|
||||
raise KeyIsEmptyStringException(index_range_key)
|
||||
|
||||
return hash_value, range_comparison, range_values # type: ignore[return-value]
|
||||
|
@ -14,6 +14,7 @@ from .exceptions import (
|
||||
MockValidationException,
|
||||
ResourceNotFoundException,
|
||||
UnknownKeyType,
|
||||
KeyIsEmptyStringException,
|
||||
)
|
||||
from moto.dynamodb.models import dynamodb_backends, Table, DynamoDBBackend
|
||||
from moto.dynamodb.models.utilities import dynamo_json_dump
|
||||
@ -554,10 +555,7 @@ class DynamoHandler(BaseResponse):
|
||||
key = self.body["Key"]
|
||||
empty_keys = [k for k, v in key.items() if not next(iter(v.values()))]
|
||||
if empty_keys:
|
||||
raise MockValidationException(
|
||||
"One or more parameter values are not valid. The AttributeValue for a key attribute cannot contain an "
|
||||
f"empty string value. Key: {empty_keys[0]}"
|
||||
)
|
||||
raise KeyIsEmptyStringException(empty_keys[0])
|
||||
|
||||
projection_expression = self._get_projection_expression()
|
||||
attributes_to_get = self.body.get("AttributesToGet")
|
||||
|
@ -3,6 +3,7 @@ import pytest
|
||||
|
||||
from moto import mock_dynamodb
|
||||
from botocore.exceptions import ClientError
|
||||
from boto3.dynamodb.conditions import Key
|
||||
from moto.dynamodb.limits import HASH_KEY_MAX_LENGTH, RANGE_KEY_MAX_LENGTH
|
||||
|
||||
|
||||
@ -323,3 +324,40 @@ def test_item_add_empty_key_exception():
|
||||
ex.value.response["Error"]["Message"]
|
||||
== "One or more parameter values are not valid. The AttributeValue for a key attribute cannot contain an empty string value. Key: forum_name"
|
||||
)
|
||||
|
||||
|
||||
@mock_dynamodb
|
||||
def test_query_empty_key_exception():
|
||||
name = "TestTable"
|
||||
conn = boto3.client("dynamodb", region_name="us-west-2")
|
||||
conn.create_table(
|
||||
TableName=name,
|
||||
KeySchema=[
|
||||
{"AttributeName": "hk", "KeyType": "HASH"},
|
||||
{"AttributeName": "rk", "KeyType": "RANGE"},
|
||||
],
|
||||
AttributeDefinitions=[
|
||||
{"AttributeName": "hk", "AttributeType": "S"},
|
||||
{"AttributeName": "rk", "AttributeType": "S"},
|
||||
],
|
||||
ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5},
|
||||
)
|
||||
table = boto3.resource("dynamodb", "us-west-2").Table(name)
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
table.query(KeyConditionExpression=Key("hk").eq(""))
|
||||
assert ex.value.response["Error"]["Code"] == "ValidationException"
|
||||
assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400
|
||||
assert (
|
||||
ex.value.response["Error"]["Message"]
|
||||
== "One or more parameter values are not valid. The AttributeValue for a key attribute cannot contain an empty string value. Key: hk"
|
||||
)
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
table.query(KeyConditionExpression=Key("hk").eq("sth") & Key("rk").eq(""))
|
||||
assert ex.value.response["Error"]["Code"] == "ValidationException"
|
||||
assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400
|
||||
assert (
|
||||
ex.value.response["Error"]["Message"]
|
||||
== "One or more parameter values are not valid. The AttributeValue for a key attribute cannot contain an empty string value. Key: rk"
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user