]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
fix: don't clobber an error from the server with a server disconnection
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Wed, 8 Jan 2025 00:21:22 +0000 (01:21 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Fri, 10 Jan 2025 00:39:29 +0000 (01:39 +0100)
The server error is assumed to contain more information, as it is
returned as a result, whereas a communication error caused by a server
disconnection will only make available the error message.

Close #988 (but we need to fix the Cython side too).

docs/news.rst
psycopg/psycopg/generators.py

index 2e011ad4b45ccdd550f6645a8f12bc7145c21252..94975446d40086a31d278afa40121bebf9997085 100644 (file)
@@ -17,6 +17,9 @@ Psycopg 3.2.4 (unreleased)
   is not running (:ticket:`#962`).
 - Make sure that the notifies callback is called during the use of the
   `~Connection.notifies()` generator (:ticket:`#972`).
+- Raise `~errors.IdleInTransactionSessionTimeout` instead of a generic
+  `OperationalError` upon hitting an idle-in-transaction timeout
+  (:ticket:`#988`).
 
 
 Current release
index 5d6554f36fb1585f55c0f20ff11c0d2846b4edf4..67a31878dc761f83ad61f7fd7f37195ce17a339e 100644 (file)
@@ -46,6 +46,7 @@ COMMAND_OK = pq.ExecStatus.COMMAND_OK
 COPY_OUT = pq.ExecStatus.COPY_OUT
 COPY_IN = pq.ExecStatus.COPY_IN
 COPY_BOTH = pq.ExecStatus.COPY_BOTH
+FATAL_ERROR = pq.ExecStatus.FATAL_ERROR
 PIPELINE_SYNC = pq.ExecStatus.PIPELINE_SYNC
 
 WAIT_R = Wait.R
@@ -176,7 +177,19 @@ def _fetch_many(pgconn: PGconn) -> PQGen[list[PGresult]]:
     """
     results: list[PGresult] = []
     while True:
-        res = yield from _fetch(pgconn)
+        try:
+            res = yield from _fetch(pgconn)
+        except e.DatabaseError:
+            # What might have happened here is that a previuos error
+            # disconnected the connection, for example a idle in transaction
+            # timeout. Check if we had received an error before, and raise it
+            # as exception, because it should contain more details. See #988.
+            for res in results:
+                if res.status == FATAL_ERROR:
+                    raise e.error_from_result(res, encoding=pgconn._encoding) from None
+            else:
+                raise
+
         if not res:
             break