]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
fix(c): don't clobber an error from the server with a server disconnection
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Wed, 8 Jan 2025 00:33:52 +0000 (01:33 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Fri, 10 Jan 2025 00:39:29 +0000 (01:39 +0100)
Instead of raising the exception here, return the result and let the
caller handle the exception. This might make code paths more uniform and
helps the C implementation, because we actually never call
`error_from_result()` in the Cython code.

psycopg/psycopg/generators.py
psycopg_c/psycopg_c/_psycopg/generators.pyx

index 67a31878dc761f83ad61f7fd7f37195ce17a339e..44e9f4e992dcafbd528a10931c5d7e466f2ef48d 100644 (file)
@@ -180,13 +180,13 @@ def _fetch_many(pgconn: PGconn) -> PQGen[list[PGresult]]:
         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
+            # 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: if that's the case
+            # just exit the loop. Our callers will handle this error and raise
+            # it as an exception.
+            if any(res.status == FATAL_ERROR for res in results):
+                break
             else:
                 raise
 
index a908577c2a3689d06a973e24f4b16a6a5ca3218e..c280d1389ce3ceb2f41006003456bb8b977a2e9d 100644 (file)
@@ -173,9 +173,21 @@ def fetch_many(pq.PGconn pgconn) -> PQGen[list[PGresult]]:
     cdef libpq.PGresult *pgres
 
     while True:
-        result = yield from fetch(pgconn)
+        try:
+            result = 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.
+            if any(result.status == libpq.PGRES_FATAL_ERROR for res in results):
+                break
+            else:
+                raise
+
         if result is None:
             break
+
         results.append(result)
         pgres = result._pgresult_ptr