From: Daniele Varrazzo Date: Fri, 2 May 2025 22:18:10 +0000 (+0200) Subject: fix: improve error message trying to fetch from a no recordset result X-Git-Tag: 3.2.8~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a158a5b70a292ecbdd6cc858ef319df279679fdd;p=thirdparty%2Fpsycopg.git fix: improve error message trying to fetch from a no recordset result Print the last command status with the error. For example: the last operation didn't produce records (command status: NOTIFY) or, if the result doesn't even have a command status: the last operation didn't produce records (result status: EMPTY_QUERY) --- diff --git a/psycopg/psycopg/_cursor_base.py b/psycopg/psycopg/_cursor_base.py index 3a1d6d45b..f6e85f190 100644 --- a/psycopg/psycopg/_cursor_base.py +++ b/psycopg/psycopg/_cursor_base.py @@ -579,7 +579,17 @@ class BaseCursor(Generic[ConnectionType, Row]): elif status == PIPELINE_ABORTED: raise e.PipelineAborted("pipeline aborted") else: - raise e.ProgrammingError("the last operation didn't produce a result") + if res.command_status: + detail = f" (command status: {res.command_status.decode()})" + else: + try: + status_name = pq.ExecStatus(status).name + except ValueError: + status_name = f"{status} - unknown" + detail = f" (result status: {status_name})" + raise e.ProgrammingError( + f"the last operation didn't produce records{detail}" + ) def _check_copy_result(self, result: PGresult) -> None: """ diff --git a/tests/test_cursor_common.py b/tests/test_cursor_common.py index f1fcf665d..d99f734e0 100644 --- a/tests/test_cursor_common.py +++ b/tests/test_cursor_common.py @@ -865,3 +865,21 @@ def test_message_0x33(conn): def test_typeinfo(conn): info = TypeInfo.fetch(conn, "jsonb") assert info is not None + + +def test_error_no_result(conn): + cur = conn.cursor() + with pytest.raises(psycopg.ProgrammingError, match="no result available"): + cur.fetchone() + + cur.execute("set timezone to utc") + with pytest.raises( + psycopg.ProgrammingError, match="last operation.*command status: SET" + ): + cur.fetchone() + + cur.execute("") + with pytest.raises( + psycopg.ProgrammingError, match="last operation.*result status: EMPTY_QUERY" + ): + cur.fetchone() diff --git a/tests/test_cursor_common_async.py b/tests/test_cursor_common_async.py index 9a96785c8..03e5ef6b0 100644 --- a/tests/test_cursor_common_async.py +++ b/tests/test_cursor_common_async.py @@ -872,3 +872,21 @@ async def test_message_0x33(aconn): async def test_typeinfo(aconn): info = await TypeInfo.fetch(aconn, "jsonb") assert info is not None + + +async def test_error_no_result(aconn): + cur = aconn.cursor() + with pytest.raises(psycopg.ProgrammingError, match="no result available"): + await cur.fetchone() + + await cur.execute("set timezone to utc") + with pytest.raises( + psycopg.ProgrammingError, match="last operation.*command status: SET" + ): + await cur.fetchone() + + await cur.execute("") + with pytest.raises( + psycopg.ProgrammingError, match="last operation.*result status: EMPTY_QUERY" + ): + await cur.fetchone()