Skip to content

Commit d3dbf15

Browse files
authored
DynamoDB: query() should handle GSI's without range key (#7729)
1 parent b19afe8 commit d3dbf15

2 files changed

Lines changed: 45 additions & 4 deletions

File tree

moto/dynamodb/models/table.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -702,11 +702,12 @@ def query(
702702
key for key in index.schema if key["KeyType"] == "RANGE"
703703
][0]
704704
except IndexError:
705-
if isinstance(index, GlobalSecondaryIndex):
706-
# If we're querying a GSI that does not have an index, the main hash key acts as a range key
707-
index_range_key = {"AttributeName": self.hash_key_attr}
705+
if isinstance(index, GlobalSecondaryIndex) and self.range_key_attr:
706+
# If we're querying a GSI that does not have a range key, the main range key acts as a range key
707+
index_range_key = {"AttributeName": self.range_key_attr}
708708
else:
709-
index_range_key = None
709+
# If we don't have a range key on the main table either, the hash key acts as a range key
710+
index_range_key = {"AttributeName": self.hash_key_attr}
710711
if range_comparison:
711712
raise ValueError(
712713
f"Range Key comparison but no range key found for index: {index_name}"

tests/test_dynamodb/test_dynamodb_query.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,46 @@ def test_query_gsi_pagination(table_name=None):
240240
]
241241

242242

243+
@pytest.mark.aws_verified
244+
@dynamodb_aws_verified(add_range=True, add_gsi=True)
245+
def test_query_gsi_pagination_with_string_range(table_name=None):
246+
dynamodb = boto3.resource("dynamodb", region_name="us-east-1")
247+
table = dynamodb.Table(table_name)
248+
249+
for i in range(3, 7):
250+
table.put_item(Item={"pk": "the-key", "sk": f"{i}", "gsi_pk": "johndoe"})
251+
252+
for i in range(9, 6, -1):
253+
table.put_item(Item={"pk": "the-key", "sk": f"{i}", "gsi_pk": "johndoe"})
254+
255+
for i in range(3):
256+
table.put_item(Item={"pk": "the-key", "sk": f"{i}", "gsi_pk": "johndoe"})
257+
258+
page1 = table.query(
259+
KeyConditionExpression=Key("gsi_pk").eq("johndoe"),
260+
IndexName="test_gsi",
261+
Limit=6,
262+
)
263+
assert page1["Count"] == 6
264+
assert page1["ScannedCount"] == 6
265+
assert len(page1["Items"]) == 6
266+
267+
page2 = table.query(
268+
KeyConditionExpression=Key("gsi_pk").eq("johndoe"),
269+
IndexName="test_gsi",
270+
Limit=6,
271+
ExclusiveStartKey=page1["LastEvaluatedKey"],
272+
)
273+
assert page2["Count"] == 4
274+
assert page2["ScannedCount"] == 4
275+
assert len(page2["Items"]) == 4
276+
assert "LastEvaluatedKey" not in page2
277+
278+
results = page1["Items"] + page2["Items"]
279+
subjects = set([int(r["sk"]) for r in results])
280+
assert subjects == set(range(10))
281+
282+
243283
@pytest.mark.aws_verified
244284
@dynamodb_aws_verified(add_range=True, numeric_gsi_range=True)
245285
def test_query_gsi_pagination_with_numeric_range(table_name=None):

0 commit comments

Comments
 (0)