diff --git a/moto/dynamodb/parsing/key_condition_expression.py b/moto/dynamodb/parsing/key_condition_expression.py index 1ecd15fce..0b30c78dc 100644 --- a/moto/dynamodb/parsing/key_condition_expression.py +++ b/moto/dynamodb/parsing/key_condition_expression.py @@ -150,11 +150,11 @@ def parse_expression( # hashkey = :id and sortkey = :sk # ^ if current_stage == EXPRESSION_STAGES.KEY_VALUE: - key_values.append( - expression_attribute_values.get( - current_phrase, {"S": current_phrase} + if current_phrase not in expression_attribute_values: + raise MockValidationException( + "Invalid condition in KeyConditionExpression: Multiple attribute names used in one condition" ) - ) + key_values.append(expression_attribute_values[current_phrase]) results.append((key_name, comparison, key_values)) break if crnt_char == "(": diff --git a/tests/test_dynamodb/exceptions/test_dynamodb_exceptions.py b/tests/test_dynamodb/exceptions/test_dynamodb_exceptions.py index 97e7d9e2f..f7b7284a3 100644 --- a/tests/test_dynamodb/exceptions/test_dynamodb_exceptions.py +++ b/tests/test_dynamodb/exceptions/test_dynamodb_exceptions.py @@ -1094,3 +1094,22 @@ def test_query_with_empty_filter_expression(): assert ( err["Message"] == "Invalid FilterExpression: The expression can not be empty;" ) + + +@mock_dynamodb +def test_query_with_missing_expression_attribute(): + ddb = boto3.resource("dynamodb", region_name="us-west-2") + ddb.create_table(TableName="test", BillingMode="PAY_PER_REQUEST", **table_schema) + client = boto3.client("dynamodb", region_name="us-west-2") + with pytest.raises(ClientError) as exc: + client.query( + TableName="test", + KeyConditionExpression="#part_key=some_value", + ExpressionAttributeNames={"#part_key": "partitionKey"}, + ) + err = exc.value.response["Error"] + assert err["Code"] == "ValidationException" + assert ( + err["Message"] + == "Invalid condition in KeyConditionExpression: Multiple attribute names used in one condition" + ) diff --git a/tests/test_dynamodb/models/test_key_condition_expression_parser.py b/tests/test_dynamodb/models/test_key_condition_expression_parser.py index fdb82ff5b..1c502e9d2 100644 --- a/tests/test_dynamodb/models/test_key_condition_expression_parser.py +++ b/tests/test_dynamodb/models/test_key_condition_expression_parser.py @@ -31,21 +31,6 @@ class TestHashKey: ) assert exc.value.message == "Query condition missed key schema element: job_id" - def test_unknown_hash_value(self): - # TODO: is this correct? I'd assume that this should throw an error instead - # Revisit after test in exceptions.py passes - kce = "job_id = :unknown" - eav = {":id": {"S": "asdasdasd"}} - desired_hash_key, comparison, range_values = parse_expression( - expression_attribute_values=eav, - key_condition_expression=kce, - schema=self.schema, - expression_attribute_names=dict(), - ) - assert desired_hash_key == {"S": ":unknown"} - assert comparison is None - assert range_values == [] - class TestHashAndRangeKey: schema = [ @@ -185,9 +170,8 @@ class TestHashAndRangeKey: ], ) def test_brackets(self, expr): - eav = {":id": "pk", ":sk1": "19", ":sk2": "21"} desired_hash_key, comparison, range_values = parse_expression( - expression_attribute_values=eav, + expression_attribute_values={":id": "pk", ":sk": "19"}, key_condition_expression=expr, schema=self.schema, expression_attribute_names=dict(), diff --git a/tests/test_dynamodb/test_dynamodb.py b/tests/test_dynamodb/test_dynamodb.py index 81e4dc3e6..07c405071 100644 --- a/tests/test_dynamodb/test_dynamodb.py +++ b/tests/test_dynamodb/test_dynamodb.py @@ -1977,15 +1977,6 @@ def test_query_missing_expr_names(): assert resp["Count"] == 1 assert resp["Items"][0]["client"]["S"] == "test1" - resp = client.query( - TableName="test1", - KeyConditionExpression=":name=test2", - ExpressionAttributeNames={":name": "client"}, - ) - - assert resp["Count"] == 1 - assert resp["Items"][0]["client"]["S"] == "test2" - # https://github.com/getmoto/moto/issues/2328 @mock_dynamodb