]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Make sue ServerCursor.execute() can be used more than once
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Wed, 10 Feb 2021 17:50:03 +0000 (18:50 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Wed, 10 Feb 2021 17:50:03 +0000 (18:50 +0100)
psycopg3/psycopg3/server_cursor.py
tests/test_server_cursor.py
tests/test_server_cursor_async.py

index 289485edc0fe86bd2a2e5d8235306cd599aaeb16..e0e66e999c492ed0fa79051f8a1e56a72dfb74c4 100644 (file)
@@ -53,6 +53,12 @@ class ServerCursorHelper(Generic[ConnectionType]):
     ) -> PQGen[None]:
         """Generator implementing `ServerCursor.execute()`."""
         conn = cur._conn
+
+        # If the cursor is being reused, the previous one must be closed.
+        if self.described:
+            yield from self._close_gen(cur)
+            self.described = False
+
         yield from cur._start_query(query)
         pgq = cur._convert_query(query, params)
         cur._execute_send(pgq)
index ff9c2559bfbb80ba87fcb4903995902e84bf79c8..78d456507ae804bb673a33c507e73049cc747cc3 100644 (file)
@@ -94,6 +94,20 @@ def test_warn_close(conn, recwarn):
     assert ".close()" in str(recwarn.pop(ResourceWarning).message)
 
 
+def test_execute_reuse(conn):
+    with conn.cursor("foo") as cur:
+        cur.execute("select generate_series(1, %s) as foo", (3,))
+        assert cur.fetchone() == (1,)
+
+        cur.execute(
+            "select %s::text as bar, %s::text as baz", ("hello", "world")
+        )
+        assert cur.fetchone() == ("hello", "world")
+        assert cur.description[0].name == "bar"
+        assert cur.description[0].type_code == cur.adapters.types["text"].oid
+        assert cur.description[1].name == "baz"
+
+
 def test_executemany(conn):
     cur = conn.cursor("foo")
     with pytest.raises(e.NotSupportedError):
index 685c559285cf8a0ec88d309685d559bd8a048ed5..4a34655351b2b72b5600495dd85d4b84f30723ac 100644 (file)
@@ -96,6 +96,20 @@ async def test_warn_close(aconn, recwarn):
     assert ".close()" in str(recwarn.pop(ResourceWarning).message)
 
 
+async def test_execute_reuse(aconn):
+    async with aconn.cursor("foo") as cur:
+        await cur.execute("select generate_series(1, %s) as foo", (3,))
+        assert await cur.fetchone() == (1,)
+
+        await cur.execute(
+            "select %s::text as bar, %s::text as baz", ("hello", "world")
+        )
+        assert await cur.fetchone() == ("hello", "world")
+        assert cur.description[0].name == "bar"
+        assert cur.description[0].type_code == cur.adapters.types["text"].oid
+        assert cur.description[1].name == "baz"
+
+
 async def test_executemany(aconn):
     cur = aconn.cursor("foo")
     with pytest.raises(e.NotSupportedError):