From 9e92653e6f2f026ae3ed5689f769c5ad362052ac Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi Date: Thu, 13 Aug 2026 15:34:58 +0900 Subject: [PATCH 1/2] fix(django-cf): fix order-by not working --- .../django-cf/django_cf/db/base_engine.py | 29 +++++------ .../in_worker/worker/src/test_asgi_d1.py | 17 +++++-- .../in_worker/worker/src/test_base_engine.py | 51 +++++++++++++++---- 3 files changed, 67 insertions(+), 30 deletions(-) diff --git a/packages/django-cf/django_cf/db/base_engine.py b/packages/django-cf/django_cf/db/base_engine.py index 76858de6..020c95d1 100644 --- a/packages/django-cf/django_cf/db/base_engine.py +++ b/packages/django-cf/django_cf/db/base_engine.py @@ -201,6 +201,7 @@ class CFResult: def __init__(self, data): self.data = data + self._position = 0 def __iter__(self): return iter(self.data) @@ -212,29 +213,23 @@ def set_rowcount(self, value): self.rowcount = value def fetchone(self): - if len(self.data) > 0: - return self.data.pop() + if self._position < len(self.data): + row = self.data[self._position] + self._position += 1 + return row return None def fetchall(self): - ret = [] - while True: - row = self.fetchone() - if row is None: - break - ret.append(row) + ret = self.data[self._position :] + self._position = len(self.data) return ret def fetchmany(self, size=1): - ret = [] - while size > 0: - row = self.fetchone() - if row is None: - break - ret.append(row) - if size is not None: - size -= 1 - + if size <= 0: + return [] + end = min(self._position + size, len(self.data)) + ret = self.data[self._position : end] + self._position = end return ret @staticmethod diff --git a/packages/django-cf/tests/in_worker/worker/src/test_asgi_d1.py b/packages/django-cf/tests/in_worker/worker/src/test_asgi_d1.py index d42fe142..71e8bef4 100644 --- a/packages/django-cf/tests/in_worker/worker/src/test_asgi_d1.py +++ b/packages/django-cf/tests/in_worker/worker/src/test_asgi_d1.py @@ -62,8 +62,10 @@ async def iterate_view(request): for value in ["charlie", "alpha", "bravo"]: await AsgiD1Record.objects.using("d1").acreate(value=value) + order_field = "-value" if request.GET.get("direction") == "desc" else "value" + values = [] - queryset = AsgiD1Record.objects.using("d1").order_by("value") + queryset = AsgiD1Record.objects.using("d1").order_by(order_field) async for record in queryset: values.append(record.value) @@ -148,9 +150,18 @@ async def test_asgi_d1_orm_update_returns_affected_rows_and_persists_value(): @pytest.mark.asyncio -async def test_asgi_d1_orm_async_iteration_returns_all_rows(): +async def test_asgi_d1_orm_async_iteration_returns_all_rows_ascending(): response, payload = await _run_d1_request("/asgi/d1/iterate/") assert response.status == 200 assert payload is not None - assert sorted(payload["values"]) == ["alpha", "bravo", "charlie"] + assert payload["values"] == ["alpha", "bravo", "charlie"] + + +@pytest.mark.asyncio +async def test_asgi_d1_orm_async_iteration_returns_all_rows_descending(): + response, payload = await _run_d1_request("/asgi/d1/iterate/?direction=desc") + + assert response.status == 200 + assert payload is not None + assert payload["values"] == ["charlie", "bravo", "alpha"] diff --git a/packages/django-cf/tests/in_worker/worker/src/test_base_engine.py b/packages/django-cf/tests/in_worker/worker/src/test_base_engine.py index f6793e83..0a837e4b 100644 --- a/packages/django-cf/tests/in_worker/worker/src/test_base_engine.py +++ b/packages/django-cf/tests/in_worker/worker/src/test_base_engine.py @@ -50,8 +50,10 @@ def test_fetchone_with_data(self): result = CFResult(data) row = result.fetchone() - assert row == (3, "c") - assert len(result.data) == 2 + assert row == (1, "a") + assert result.data == data + assert result.fetchall() == [(2, "b"), (3, "c")] + assert result.fetchone() is None def test_fetchone_empty(self): from django_cf.db.base_engine import CFResult @@ -66,8 +68,9 @@ def test_fetchall(self): data = [(1, "a"), (2, "b"), (3, "c")] result = CFResult(data) - assert result.fetchall() == [(3, "c"), (2, "b"), (1, "a")] - assert len(result.data) == 0 + assert result.fetchall() == [(1, "a"), (2, "b"), (3, "c")] + assert result.data == data + assert result.fetchall() == [] def test_fetchall_empty(self): from django_cf.db.base_engine import CFResult @@ -80,8 +83,8 @@ def test_fetchmany_default(self): data = [(1, "a"), (2, "b"), (3, "c")] result = CFResult(data) - assert result.fetchmany() == [(3, "c")] - assert len(result.data) == 2 + assert result.fetchmany() == [(1, "a")] + assert result.data == data def test_fetchmany_specific_size(self): from django_cf.db.base_engine import CFResult @@ -90,8 +93,24 @@ def test_fetchmany_specific_size(self): result = CFResult(data) rows = result.fetchmany(2) - assert len(rows) == 2 - assert len(result.data) == 1 + assert rows == [(1, "a"), (2, "b")] + assert result.data == data + assert result.fetchmany(2) == [(3, "c")] + assert result.fetchmany(2) == [] + + def test_fetchmany_non_positive_size_does_not_advance(self): + from django_cf.db.base_engine import CFResult + + data = [(1, "a"), (2, "b"), (3, "c")] + result = CFResult(data) + + assert result.fetchmany(0) == [] + assert result.fetchone() == (1, "a") + + result = CFResult(data) + + assert result.fetchmany(-1) == [] + assert result.fetchone() == (1, "a") def test_fetchmany_more_than_available(self): from django_cf.db.base_engine import CFResult @@ -100,8 +119,20 @@ def test_fetchmany_more_than_available(self): result = CFResult(data) rows = result.fetchmany(5) - assert len(rows) == 2 - assert len(result.data) == 0 + assert rows == [(1, "a"), (2, "b")] + assert result.data == data + assert result.fetchone() is None + + def test_fetchone_then_fetchall_returns_remaining_rows(self): + from django_cf.db.base_engine import CFResult + + data = [(1, "a"), (2, "b"), (3, "c")] + result = CFResult(data) + + assert result.fetchone() == (1, "a") + assert result.fetchall() == [(2, "b"), (3, "c")] + assert result.data == data + assert result.fetchone() is None def test_from_object_with_list_rows(self): from django_cf.db.base_engine import CFResult From 60b0d5914e640b333591ec9fc6c0fb251a8fb81e Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi Date: Thu, 13 Aug 2026 15:57:13 +0900 Subject: [PATCH 2/2] chore: fix test --- packages/django-cf/tests/in_worker/worker/src/test_asgi_d1.py | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/django-cf/tests/in_worker/worker/src/test_asgi_d1.py b/packages/django-cf/tests/in_worker/worker/src/test_asgi_d1.py index 71e8bef4..ee548e73 100644 --- a/packages/django-cf/tests/in_worker/worker/src/test_asgi_d1.py +++ b/packages/django-cf/tests/in_worker/worker/src/test_asgi_d1.py @@ -58,7 +58,6 @@ async def update_view(request): async def iterate_view(request): - del request for value in ["charlie", "alpha", "bravo"]: await AsgiD1Record.objects.using("d1").acreate(value=value)