]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
fix: raise a warning if nextset is used after execute in pipeline mode 613/head
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Tue, 1 Aug 2023 10:57:48 +0000 (11:57 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Tue, 1 Aug 2023 11:06:06 +0000 (12:06 +0100)
So far have accumulated results, unlike in no-pipeline mode, where
results have been discarded. But this proved to be not reliable, so we
will forbid it in 3.2.

See #604

psycopg/psycopg/cursor.py
tests/test_pipeline.py
tests/test_pipeline_async.py

index 6048bbf664e116e8d819a7f1a9b0b3f9e06a4062..349f6ef5c7438aadda48b095af9f38a1fa54ee84 100644 (file)
@@ -9,6 +9,7 @@ from types import TracebackType
 from typing import Any, Generic, Iterable, Iterator, List
 from typing import Optional, NoReturn, Sequence, Tuple, Type, TypeVar
 from typing import overload, TYPE_CHECKING
+from warnings import warn
 from contextlib import contextmanager
 
 from . import pq
@@ -156,6 +157,18 @@ class BaseCursor(Generic[ConnectionType, Row]):
         Return `!True` if a new result is available, which will be the one
         methods `!fetch*()` will operate on.
         """
+        # Raise a warning if people is calling nextset() in pipeline mode
+        # after a sequence of execute() in pipeline mode. Pipeline accumulating
+        # execute() results in the cursor is an unintended difference w.r.t.
+        # non-pipeline mode.
+        if self._execmany_returning is None and self._conn._pipeline:
+            warn(
+                "using nextset() in pipeline mode for several execute() is"
+                " deprecated and will be dropped in 3.2; please use different"
+                " cursors to receive more than one result",
+                DeprecationWarning,
+            )
+
         if self._iresult < len(self._results) - 1:
             self._select_current_result(self._iresult + 1)
             return True
index 0a0e93fab112829a1f23a09f5ba8f4d6956509d5..12180bdebaa07f159491b017cb54478b4ef44bf7 100644 (file)
@@ -593,3 +593,23 @@ def test_concurrency(conn):
     assert s == sum(values)
     (after,) = conn.execute("select value from accessed").fetchone()
     assert after > before
+
+
+def test_execute_nextset_warning(conn):
+    cur = conn.cursor()
+    cur.execute("select 1")
+    cur.execute("select 2")
+
+    assert cur.fetchall() == [(2,)]
+    assert not cur.nextset()
+    assert cur.fetchall() == []
+
+    with conn.pipeline():
+        cur.execute("select 1")
+        cur.execute("select 2")
+
+        # WARNING: this behavior is unintentional and will be changed in 3.2
+        assert cur.fetchall() == [(1,)]
+        with pytest.warns(DeprecationWarning, match="nextset"):
+            assert cur.nextset()
+        assert cur.fetchall() == [(2,)]
index 488036a7e9ae9c6acc3bddccdb3daed989182415..484cce4dcab0c69df69d902582f55c35d5c2955f 100644 (file)
@@ -601,3 +601,23 @@ async def test_concurrency(aconn):
     assert s == sum(values)
     (after,) = await (await aconn.execute("select value from accessed")).fetchone()
     assert after > before
+
+
+async def test_execute_nextset_warning(aconn):
+    cur = aconn.cursor()
+    await cur.execute("select 1")
+    await cur.execute("select 2")
+
+    assert (await cur.fetchall()) == [(2,)]
+    assert not cur.nextset()
+    assert (await cur.fetchall()) == []
+
+    async with aconn.pipeline():
+        await cur.execute("select 1")
+        await cur.execute("select 2")
+
+        # WARNING: this behavior is unintentional and will be changed in 3.2
+        assert (await cur.fetchall()) == [(1,)]
+        with pytest.warns(DeprecationWarning, match="nextset"):
+            assert cur.nextset()
+        assert (await cur.fetchall()) == [(2,)]