mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-06 15:24:56 +08:00
Adjust error-handling logic in libpq. For the first time, libpq copes
sanely with running out of memory for a query result.
This commit is contained in:
parent
90903069e9
commit
5493ecc3a5
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.135 2003/05/08 18:16:37 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.136 2003/05/26 20:05:20 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -55,7 +55,7 @@ static void parseInput(PGconn *conn);
|
|||||||
static void handleSendFailure(PGconn *conn);
|
static void handleSendFailure(PGconn *conn);
|
||||||
static void handleSyncLoss(PGconn *conn, char id, int msgLength);
|
static void handleSyncLoss(PGconn *conn, char id, int msgLength);
|
||||||
static int getRowDescriptions(PGconn *conn);
|
static int getRowDescriptions(PGconn *conn);
|
||||||
static int getAnotherTuple(PGconn *conn);
|
static int getAnotherTuple(PGconn *conn, int msgLength);
|
||||||
static int getParameterStatus(PGconn *conn);
|
static int getParameterStatus(PGconn *conn);
|
||||||
static int getNotify(PGconn *conn);
|
static int getNotify(PGconn *conn);
|
||||||
|
|
||||||
@ -835,17 +835,28 @@ parseInput(PGconn *conn)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'D': /* Data Row */
|
case 'D': /* Data Row */
|
||||||
if (conn->result != NULL)
|
if (conn->result != NULL &&
|
||||||
|
conn->result->resultStatus == PGRES_TUPLES_OK)
|
||||||
{
|
{
|
||||||
/* Read another tuple of a normal query response */
|
/* Read another tuple of a normal query response */
|
||||||
if (getAnotherTuple(conn))
|
if (getAnotherTuple(conn, msgLength))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (conn->result != NULL &&
|
||||||
|
conn->result->resultStatus == PGRES_FATAL_ERROR)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We've already choked for some reason. Just discard
|
||||||
|
* tuples till we get to the end of the query.
|
||||||
|
*/
|
||||||
|
conn->inCursor += msgLength;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
snprintf(noticeWorkspace, sizeof(noticeWorkspace),
|
/* Set up to report error at end of query */
|
||||||
|
printfPQExpBuffer(&conn->errorMessage,
|
||||||
libpq_gettext("server sent data (\"D\" message) without prior row description (\"T\" message)\n"));
|
libpq_gettext("server sent data (\"D\" message) without prior row description (\"T\" message)\n"));
|
||||||
DONOTICE(conn, noticeWorkspace);
|
saveErrorResult(conn);
|
||||||
/* Discard the unexpected message */
|
/* Discard the unexpected message */
|
||||||
conn->inCursor += msgLength;
|
conn->inCursor += msgLength;
|
||||||
}
|
}
|
||||||
@ -888,6 +899,7 @@ parseInput(PGconn *conn)
|
|||||||
id);
|
id);
|
||||||
/* build an error result holding the error message */
|
/* build an error result holding the error message */
|
||||||
saveErrorResult(conn);
|
saveErrorResult(conn);
|
||||||
|
/* not sure if we will see more, so go to ready state */
|
||||||
conn->asyncStatus = PGASYNC_READY;
|
conn->asyncStatus = PGASYNC_READY;
|
||||||
/* Discard the unexpected message */
|
/* Discard the unexpected message */
|
||||||
conn->inCursor += msgLength;
|
conn->inCursor += msgLength;
|
||||||
@ -931,6 +943,7 @@ handleSyncLoss(PGconn *conn, char id, int msgLength)
|
|||||||
pqsecure_close(conn);
|
pqsecure_close(conn);
|
||||||
closesocket(conn->sock);
|
closesocket(conn->sock);
|
||||||
conn->sock = -1;
|
conn->sock = -1;
|
||||||
|
conn->asyncStatus = PGASYNC_READY; /* drop out of GetResult wait loop */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1023,7 +1036,7 @@ getRowDescriptions(PGconn *conn)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
getAnotherTuple(PGconn *conn)
|
getAnotherTuple(PGconn *conn, int msgLength)
|
||||||
{
|
{
|
||||||
PGresult *result = conn->result;
|
PGresult *result = conn->result;
|
||||||
int nfields = result->numAttributes;
|
int nfields = result->numAttributes;
|
||||||
@ -1050,12 +1063,11 @@ getAnotherTuple(PGconn *conn)
|
|||||||
if (tupnfields != nfields)
|
if (tupnfields != nfields)
|
||||||
{
|
{
|
||||||
/* Replace partially constructed result with an error result */
|
/* Replace partially constructed result with an error result */
|
||||||
pqClearAsyncResult(conn);
|
|
||||||
printfPQExpBuffer(&conn->errorMessage,
|
printfPQExpBuffer(&conn->errorMessage,
|
||||||
libpq_gettext("unexpected field count in D message\n"));
|
libpq_gettext("unexpected field count in D message\n"));
|
||||||
saveErrorResult(conn);
|
saveErrorResult(conn);
|
||||||
conn->asyncStatus = PGASYNC_READY;
|
|
||||||
/* Discard the failed message by pretending we read it */
|
/* Discard the failed message by pretending we read it */
|
||||||
|
conn->inCursor = conn->inStart + 5 + msgLength;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1102,14 +1114,15 @@ outOfMemory:
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* we do NOT use saveErrorResult() here, because of the likelihood
|
* we do NOT use saveErrorResult() here, because of the likelihood
|
||||||
* that there's not enough memory to concatenate messages...
|
* that there's not enough memory to concatenate messages. Instead,
|
||||||
|
* discard the old result first to try to win back some memory.
|
||||||
*/
|
*/
|
||||||
pqClearAsyncResult(conn);
|
pqClearAsyncResult(conn);
|
||||||
printfPQExpBuffer(&conn->errorMessage,
|
printfPQExpBuffer(&conn->errorMessage,
|
||||||
libpq_gettext("out of memory\n"));
|
libpq_gettext("out of memory for query result\n"));
|
||||||
conn->result = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
|
conn->result = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
|
||||||
conn->asyncStatus = PGASYNC_READY;
|
|
||||||
/* Discard the failed message by pretending we read it */
|
/* Discard the failed message by pretending we read it */
|
||||||
|
conn->inCursor = conn->inStart + 5 + msgLength;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user