Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Added
Fixed
^^^^^
- ``MigrationRecorder`` now uses parameterized queries; fixes MariaDB/MySQL rejecting ISO-8601 ``applied_at`` values. (#2132)
- ``QuerySet.count()`` no longer returns a negative number when ``offset()`` is greater than the total row count; it now returns ``0``.

1.1.7
-----
Expand Down
10 changes: 10 additions & 0 deletions tests/test_queryset.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,16 @@ async def test_offset_count(db, intfields_data):
assert await IntFields.all().offset(10).count() == 20


@pytest.mark.asyncio
async def test_offset_count_beyond_total(db, intfields_data):
# An offset past the total must report 0, not a negative count (the SQL
# LIMIT/OFFSET would return zero rows).
assert await IntFields.all().offset(100).count() == 0
assert await IntFields.all().offset(100).count() == len(
await IntFields.all().offset(100)
)


@pytest.mark.asyncio
async def test_offset_negative(db, intfields_data):
with pytest.raises(ParamsError, match="Offset should be non-negative number"):
Expand Down
5 changes: 4 additions & 1 deletion tortoise/queryset.py
Original file line number Diff line number Diff line change
Expand Up @@ -1571,7 +1571,10 @@ async def _execute(self) -> int:
_, result = await self._db.execute_query(*self.query.get_parameterized_sql())
if not result:
return 0
count = list(dict(result[0]).values())[0] - self._offset
# COUNT(*) ignores LIMIT/OFFSET, so the offset is applied here. Clamp at
# 0: when the offset is past the total, SQL would return 0 rows, not a
# negative count.
count = max(0, list(dict(result[0]).values())[0] - self._offset)
if self._limit and count > self._limit:
return self._limit
return count
Expand Down
Loading