diff options
Diffstat (limited to 'src/interfaces/libpq/fe-protocol3.c')
-rw-r--r-- | src/interfaces/libpq/fe-protocol3.c | 55 |
1 files changed, 44 insertions, 11 deletions
diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c index 26dbeaed97e..94b4a448b90 100644 --- a/src/interfaces/libpq/fe-protocol3.c +++ b/src/interfaces/libpq/fe-protocol3.c @@ -316,8 +316,9 @@ pqParseInput3(PGconn *conn) return; break; case 'T': /* Row Description */ - if (conn->result != NULL && - conn->result->resultStatus == PGRES_FATAL_ERROR) + if (conn->error_result || + (conn->result != NULL && + conn->result->resultStatus == PGRES_FATAL_ERROR)) { /* * We've already choked for some reason. Just discard @@ -387,8 +388,9 @@ pqParseInput3(PGconn *conn) if (getAnotherTuple(conn, msgLength)) return; } - else if (conn->result != NULL && - conn->result->resultStatus == PGRES_FATAL_ERROR) + else if (conn->error_result || + (conn->result != NULL && + conn->result->resultStatus == PGRES_FATAL_ERROR)) { /* * We've already choked for some reason. Just discard @@ -966,10 +968,18 @@ pqGetErrorNotice3(PGconn *conn, bool isError) */ if (isError) { - if (res) - pqSetResultError(res, &workBuf); pqClearAsyncResult(conn); /* redundant, but be safe */ - conn->result = res; + if (res) + { + pqSetResultError(res, &workBuf, 0); + conn->result = res; + } + else + { + /* Fall back to using the internal-error processing paths */ + conn->error_result = true; + } + if (PQExpBufferDataBroken(workBuf)) appendPQExpBufferStr(&conn->errorMessage, libpq_gettext("out of memory\n")); @@ -2116,10 +2126,33 @@ pqFunctionCall3(PGconn *conn, Oid fnid, continue; /* consume the message and exit */ conn->inStart += 5 + msgLength; - /* if we saved a result object (probably an error), use it */ - if (conn->result) - return pqPrepareAsyncResult(conn); - return PQmakeEmptyPGresult(conn, status); + + /* + * If we already have a result object (probably an error), use + * that. Otherwise, if we saw a function result message, + * report COMMAND_OK. Otherwise, the backend violated the + * protocol, so complain. + */ + if (!(conn->result || conn->error_result)) + { + if (status == PGRES_COMMAND_OK) + { + conn->result = PQmakeEmptyPGresult(conn, status); + if (!conn->result) + { + appendPQExpBufferStr(&conn->errorMessage, + libpq_gettext("out of memory\n")); + pqSaveErrorResult(conn); + } + } + else + { + appendPQExpBufferStr(&conn->errorMessage, + libpq_gettext("protocol error: no function result\n")); + pqSaveErrorResult(conn); + } + } + return pqPrepareAsyncResult(conn); case 'S': /* parameter status */ if (getParameterStatus(conn)) continue; |