From: Daniele Varrazzo Date: Mon, 28 Mar 2022 16:54:26 +0000 (+0200) Subject: fix: default executemany to not fetching results X-Git-Tag: 3.1~154 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9126318087ec5a88db398fcec7890d28b3c371a0;p=thirdparty%2Fpsycopg.git fix: default executemany to not fetching results This is a change from before, but the feature has not been released yet, so we are still in time to change it. The change addresses some uneasy feeling about unexpected increased memory usage (see #164) and may prove a win in combination with the optimization happening in pipeline mode. So, if the user is not asking for it, let's not provide it. --- diff --git a/docs/api/cursors.rst b/docs/api/cursors.rst index ddcb5af19..5cd4bef02 100644 --- a/docs/api/cursors.rst +++ b/docs/api/cursors.rst @@ -81,29 +81,26 @@ The `!Cursor` class :type query: `!str`, `!bytes`, or `sql.Composable` :param params_seq: The parameters to pass to the query :type params_seq: Sequence of Sequences or Mappings - :param returning: If `!false`, query results won't be available to fetch + :param returning: If `!True`, fetch the results of the queries executed :type returning: `!bool` This is more efficient than performing separate queries, but in case of several :sql:`INSERT` (and with some SQL creativity for massive :sql:`UPDATE` too) you may consider using `copy()`. - If the queries return data (e.g. when executing an :sql:`INSERT ... - RETURNING` or a :sql:`SELECT` with a side-effect), the result will be - available in the cursor's state, using `fetchone()` and similar - methods; results after the first will be available using `nextset()`. - In case this makes use of an unacceptable amount of memory you can use - `!returning=False` to disable returning the results. This is not - necessary if the queries return no data (e.g. on :sql:`INSERT` without - returning). + If the queries return data you want to read (e.g. when executing an + :sql:`INSERT ... RETURNING` or a :sql:`SELECT` with a side-effect), + you can specify ``returning=True``; the results will be available in + the cursor's state and can be read using `fetchone()` and similar + methods. Each input parameter will produce a separate result set: use + `nextset()` to read the results of the queries after the first one. See :ref:`query-parameters` for all the details about executing queries. .. versionchanged:: 3.1 - results are now available in the cursor state, added `!returning` - parameter to disable it. + added ``returning`` parameter to receive query results. .. automethod:: copy diff --git a/docs/news.rst b/docs/news.rst index 9821f5c92..7acfc2838 100644 --- a/docs/news.rst +++ b/docs/news.rst @@ -14,8 +14,8 @@ Psycopg 3.1 (unreleased) ^^^^^^^^^^^^^^^^^^^^^^^^ - Add :ref:`Two-Phase Commit ` support (:ticket:`#72`). -- Return results from all queries run through `~Cursor.executemany()`; each - result set can be accessed by calling `~Cursor.nextset()` (:ticket:`#164`). +- Add ``returning`` parameter to `~Cursor.executemany()` to retrieve query + results (:ticket:`#164`). - Add `pq.PGconn.trace()` and related trace functions (:ticket:`#167`). - Add ``prepare_threshold`` parameter to `Connection` init (:ticket:`#200`). - Add `Error.pgconn` and `Error.pgresult` attributes (:ticket:`#242`). diff --git a/psycopg/psycopg/cursor.py b/psycopg/psycopg/cursor.py index 2f710e18e..c114eaede 100644 --- a/psycopg/psycopg/cursor.py +++ b/psycopg/psycopg/cursor.py @@ -566,7 +566,7 @@ class Cursor(BaseCursor["Connection[Any]", Row]): query: Query, params_seq: Iterable[Params], *, - returning: bool = True, + returning: bool = False, ) -> None: """ Execute the same command with a sequence of input data. diff --git a/psycopg/psycopg/cursor_async.py b/psycopg/psycopg/cursor_async.py index 680cac8ae..3e9050cca 100644 --- a/psycopg/psycopg/cursor_async.py +++ b/psycopg/psycopg/cursor_async.py @@ -83,7 +83,7 @@ class AsyncCursor(BaseCursor["AsyncConnection[Any]", Row]): query: Query, params_seq: Iterable[Params], *, - returning: bool = True, + returning: bool = False, ) -> None: try: async with self._conn.lock: diff --git a/tests/test_cursor.py b/tests/test_cursor.py index 3ace93bce..b32a8fc9c 100644 --- a/tests/test_cursor.py +++ b/tests/test_cursor.py @@ -287,6 +287,7 @@ def test_executemany_returning(conn, execmany): cur.executemany( "insert into execmany(num, data) values (%s, %s) returning num", [(10, "hello"), (20, "world")], + returning=True, ) assert cur.rowcount == 2 assert cur.fetchone() == (10,) @@ -300,7 +301,6 @@ def test_executemany_returning_discard(conn, execmany): cur.executemany( "insert into execmany(num, data) values (%s, %s) returning num", [(10, "hello"), (20, "world")], - returning=False, ) assert cur.rowcount == 2 with pytest.raises(psycopg.ProgrammingError): @@ -313,6 +313,7 @@ def test_executemany_no_result(conn, execmany): cur.executemany( "insert into execmany(num, data) values (%s, %s)", [(10, "hello"), (20, "world")], + returning=True, ) assert cur.rowcount == 2 with pytest.raises(psycopg.ProgrammingError): diff --git a/tests/test_cursor_async.py b/tests/test_cursor_async.py index 96ece0061..20faea1db 100644 --- a/tests/test_cursor_async.py +++ b/tests/test_cursor_async.py @@ -275,6 +275,7 @@ async def test_executemany_returning(aconn, execmany): await cur.executemany( "insert into execmany(num, data) values (%s, %s) returning num", [(10, "hello"), (20, "world")], + returning=True, ) assert cur.rowcount == 2 assert (await cur.fetchone()) == (10,) @@ -288,7 +289,6 @@ async def test_executemany_returning_discard(aconn, execmany): await cur.executemany( "insert into execmany(num, data) values (%s, %s) returning num", [(10, "hello"), (20, "world")], - returning=False, ) assert cur.rowcount == 2 with pytest.raises(psycopg.ProgrammingError): @@ -301,6 +301,7 @@ async def test_executemany_no_result(aconn, execmany): await cur.executemany( "insert into execmany(num, data) values (%s, %s)", [(10, "hello"), (20, "world")], + returning=True, ) assert cur.rowcount == 2 with pytest.raises(psycopg.ProgrammingError):