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-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2b8ab6836d2997acae2e9d022e4dfad71c1beff7;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 1eeb46712..49357206a 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 d382a4bd1..2fb06e1b5 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