diff --git a/moto/dynamodb2/responses.py b/moto/dynamodb2/responses.py index 3e9fbb553..15c1130f8 100644 --- a/moto/dynamodb2/responses.py +++ b/moto/dynamodb2/responses.py @@ -356,9 +356,18 @@ class DynamoHandler(BaseResponse): if projection_expression and expression_attribute_names: expressions = [x.strip() for x in projection_expression.split(',')] + projection_expression = None for expression in expressions: + if projection_expression is not None: + projection_expression = projection_expression + ", " + else: + projection_expression = "" + if expression in expression_attribute_names: - projection_expression = projection_expression.replace(expression, expression_attribute_names[expression]) + projection_expression = projection_expression + \ + expression_attribute_names[expression] + else: + projection_expression = projection_expression + expression filter_kwargs = {} diff --git a/tests/test_dynamodb2/test_dynamodb.py b/tests/test_dynamodb2/test_dynamodb.py index fb6c0e17d..1044f0d50 100644 --- a/tests/test_dynamodb2/test_dynamodb.py +++ b/tests/test_dynamodb2/test_dynamodb.py @@ -973,6 +973,53 @@ def test_query_filter(): assert response['Count'] == 2 +@mock_dynamodb2 +def test_query_filter_overlapping_expression_prefixes(): + client = boto3.client('dynamodb', region_name='us-east-1') + dynamodb = boto3.resource('dynamodb', region_name='us-east-1') + + # Create the DynamoDB table. + client.create_table( + TableName='test1', + AttributeDefinitions=[{'AttributeName': 'client', 'AttributeType': 'S'}, {'AttributeName': 'app', 'AttributeType': 'S'}], + KeySchema=[{'AttributeName': 'client', 'KeyType': 'HASH'}, {'AttributeName': 'app', 'KeyType': 'RANGE'}], + ProvisionedThroughput={'ReadCapacityUnits': 123, 'WriteCapacityUnits': 123} + ) + + client.put_item( + TableName='test1', + Item={ + 'client': {'S': 'client1'}, + 'app': {'S': 'app1'}, + 'nested': {'M': { + 'version': {'S': 'version1'}, + 'contents': {'L': [ + {'S': 'value1'}, {'S': 'value2'}, + ]}, + }}, + }) + + table = dynamodb.Table('test1') + response = table.query( + KeyConditionExpression=Key('client').eq('client1') & Key('app').eq('app1'), + ProjectionExpression='#1, #10, nested', + ExpressionAttributeNames={ + '#1': 'client', + '#10': 'app', + } + ) + + assert response['Count'] == 1 + assert response['Items'][0] == { + 'client': 'client1', + 'app': 'app1', + 'nested': { + 'version': 'version1', + 'contents': ['value1', 'value2'] + } + } + + @mock_dynamodb2 def test_scan_filter(): client = boto3.client('dynamodb', region_name='us-east-1')