From: Daniele Varrazzo Date: Wed, 8 Jan 2025 00:33:52 +0000 (+0100) Subject: fix(c): don't clobber an error from the server with a server disconnection X-Git-Tag: 3.2.4~6^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a8262ec89e11192379b43fd28fc288a4cd251b37;p=thirdparty%2Fpsycopg.git fix(c): don't clobber an error from the server with a server disconnection 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. --- diff --git a/psycopg/psycopg/generators.py b/psycopg/psycopg/generators.py index 67a31878d..44e9f4e99 100644 --- a/psycopg/psycopg/generators.py +++ b/psycopg/psycopg/generators.py @@ -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 diff --git a/psycopg_c/psycopg_c/_psycopg/generators.pyx b/psycopg_c/psycopg_c/_psycopg/generators.pyx index a908577c2..c280d1389 100644 --- a/psycopg_c/psycopg_c/_psycopg/generators.pyx +++ b/psycopg_c/psycopg_c/_psycopg/generators.pyx @@ -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