aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/libpq/fe-protocol3.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/libpq/fe-protocol3.c')
-rw-r--r--src/interfaces/libpq/fe-protocol3.c55
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;