From: Daniele Varrazzo Date: Sun, 4 May 2025 17:03:38 +0000 (+0200) Subject: fix: fix AsyncClientCursor.rownumber after scroll() X-Git-Tag: 3.2.8~21^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e91243beec13908dbb13af9c5c639e6fadd5bee1;p=thirdparty%2Fpsycopg.git fix: fix AsyncClientCursor.rownumber after scroll() --- diff --git a/docs/news.rst b/docs/news.rst index 731ee047c..a6bf02ae7 100644 --- a/docs/news.rst +++ b/docs/news.rst @@ -13,10 +13,12 @@ Future releases Psycopg 3.2.8 (unreleased) ^^^^^^^^^^^^^^^^^^^^^^^^^^ -- Fix `DateFromTicks` and `TimeFromTicks` return values to return date and - time referred as UTC rather than the local timezone. Change - `TimestampFromTicks` to return a datetime in UTC rather than in the local - timezone (:ticket:`#1058`). +- Fix `DateFromTicks` and `TimeFromTicks` return values to return a date and a + time referred to the UTC timezone rather than to the local timezone. For + consistency, `TimestampFromTicks` to return a datetime in UTC rather than in + the local timezone (:ticket:`#1058`). +- Fix `~Cursor.rownumber` after using `~AsyncServerCursor.scroll()` on + `AsyncServerCursor` (:ticket:`#1066`). Current release diff --git a/psycopg/psycopg/_server_cursor_async.py b/psycopg/psycopg/_server_cursor_async.py index 7ac9baff8..37e0e2621 100644 --- a/psycopg/psycopg/_server_cursor_async.py +++ b/psycopg/psycopg/_server_cursor_async.py @@ -149,3 +149,8 @@ class AsyncServerCursor( async def scroll(self, value: int, mode: str = "relative") -> None: async with self._conn.lock: await self._conn.wait(self._scroll_gen(value, mode)) + # Postgres doesn't have a reliable way to report a cursor out of bound + if mode == "relative": + self._pos += value + else: + self._pos = value diff --git a/tests/test_cursor_server.py b/tests/test_cursor_server.py index d5342a689..cc2d4cb5e 100644 --- a/tests/test_cursor_server.py +++ b/tests/test_cursor_server.py @@ -382,10 +382,14 @@ def test_row_factory(conn): cur = conn.cursor("foo", row_factory=my_row_factory, scrollable=True) cur.execute("select generate_series(1, 3) as x") + assert cur.rownumber == 0 recs = cur.fetchall() + assert cur.rownumber == 3 cur.scroll(0, "absolute") + assert cur.rownumber == 0 while rec := cur.fetchone(): recs.append(rec) + assert cur.rownumber == 3 assert recs == [[1, -1], [1, -2], [1, -3]] * 2 cur.scroll(0, "absolute") @@ -458,17 +462,26 @@ def test_cant_scroll_by_default(conn): def test_scroll(conn): cur = conn.cursor("tmp", scrollable=True) cur.execute("select generate_series(0,9)") + assert cur.rownumber == 0 cur.scroll(2) + assert cur.rownumber == 2 assert cur.fetchone() == (2,) + assert cur.rownumber == 3 cur.scroll(2) + assert cur.rownumber == 5 assert cur.fetchone() == (5,) + assert cur.rownumber == 6 cur.scroll(2, mode="relative") + assert cur.rownumber == 8 assert cur.fetchone() == (8,) cur.scroll(9, mode="absolute") + assert cur.rownumber == 9 assert cur.fetchone() == (9,) + assert cur.rownumber == 10 with pytest.raises(ValueError): cur.scroll(9, mode="wat") + assert cur.rownumber == 10 cur.close() diff --git a/tests/test_cursor_server_async.py b/tests/test_cursor_server_async.py index 682859984..98ae9a278 100644 --- a/tests/test_cursor_server_async.py +++ b/tests/test_cursor_server_async.py @@ -388,10 +388,14 @@ async def test_row_factory(aconn): cur = aconn.cursor("foo", row_factory=my_row_factory, scrollable=True) await cur.execute("select generate_series(1, 3) as x") + assert cur.rownumber == 0 recs = await cur.fetchall() + assert cur.rownumber == 3 await cur.scroll(0, "absolute") + assert cur.rownumber == 0 while rec := (await cur.fetchone()): recs.append(rec) + assert cur.rownumber == 3 assert recs == [[1, -1], [1, -2], [1, -3]] * 2 await cur.scroll(0, "absolute") @@ -464,17 +468,26 @@ async def test_cant_scroll_by_default(aconn): async def test_scroll(aconn): cur = aconn.cursor("tmp", scrollable=True) await cur.execute("select generate_series(0,9)") + assert cur.rownumber == 0 await cur.scroll(2) + assert cur.rownumber == 2 assert await cur.fetchone() == (2,) + assert cur.rownumber == 3 await cur.scroll(2) + assert cur.rownumber == 5 assert await cur.fetchone() == (5,) + assert cur.rownumber == 6 await cur.scroll(2, mode="relative") + assert cur.rownumber == 8 assert await cur.fetchone() == (8,) await cur.scroll(9, mode="absolute") + assert cur.rownumber == 9 assert await cur.fetchone() == (9,) + assert cur.rownumber == 10 with pytest.raises(ValueError): await cur.scroll(9, mode="wat") + assert cur.rownumber == 10 await cur.close()