summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Momjian1999-03-14 16:42:15 +0000
committerBruce Momjian1999-03-14 16:42:15 +0000
commite2c4d41f32107b88f92a71d2c53e2ad850d93161 (patch)
tree5b72532434618e6ec36876558f75c62e3e404ef7
parent80db587e7bb2278df680513d860563dbe413a1bf (diff)
Hi,
Just in case you'd like to see what I was talking about, I am attaching my patch to src/interfaces/libpq/fe-exec.c to prevent utility functions called from SPI from locking up the client. Jerry Gay
-rw-r--r--src/interfaces/libpq/fe-exec.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 4f40801748c..34f6d624656 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.74 1999/02/13 23:22:41 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.75 1999/03/14 16:42:15 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -467,6 +467,7 @@ static void
parseInput(PGconn *conn)
{
char id;
+ static int pendingT = 0;
/*
* Loop to parse successive complete messages available in the buffer.
@@ -535,7 +536,15 @@ parseInput(PGconn *conn)
PGRES_COMMAND_OK);
if (pqGets(conn->result->cmdStatus, CMDSTATUS_LEN, conn))
return;
- conn->asyncStatus = PGASYNC_READY;
+ if (pendingT) {
+ /* Check the returned message */
+ /* if it's a SELECT in a pendingT case, */
+ /* then it probably means no rows returned. */
+ /* We clear pendingT in that case. */
+ if (strncmp(conn->result->cmdStatus, "SELECT", 6) == 0)
+ pendingT = 0;
+ }
+ if (!pendingT) conn->asyncStatus = PGASYNC_READY;
break;
case 'E': /* error return */
if (pqGets(conn->errorMessage, ERROR_MSG_LENGTH, conn))
@@ -545,10 +554,11 @@ parseInput(PGconn *conn)
/* and build an error result holding the error message */
conn->result = PQmakeEmptyPGresult(conn,
PGRES_FATAL_ERROR);
- conn->asyncStatus = PGASYNC_READY;
+ if (!pendingT) conn->asyncStatus = PGASYNC_READY;
break;
case 'Z': /* backend is ready for new query */
conn->asyncStatus = PGASYNC_IDLE;
+ pendingT = 0;
break;
case 'I': /* empty query */
/* read and throw away the closing '\0' */
@@ -563,7 +573,7 @@ parseInput(PGconn *conn)
if (conn->result == NULL)
conn->result = PQmakeEmptyPGresult(conn,
PGRES_EMPTY_QUERY);
- conn->asyncStatus = PGASYNC_READY;
+ if (!pendingT) conn->asyncStatus = PGASYNC_READY;
break;
case 'K': /* secret key data from the backend */
@@ -584,11 +594,15 @@ parseInput(PGconn *conn)
break;
case 'T': /* row descriptions (start of query
* results) */
+ if (pendingT) {
+ DONOTICE(conn, "Got second 'T' message!\n");
+ }
if (conn->result == NULL)
{
/* First 'T' in a query sequence */
if (getRowDescriptions(conn))
return;
+ pendingT = 1;
}
else
{
@@ -600,11 +614,13 @@ parseInput(PGconn *conn)
* We stop parsing until the application accepts
* the current result.
*/
+ pendingT = 0;
conn->asyncStatus = PGASYNC_READY;
return;
}
break;
case 'D': /* ASCII data tuple */
+ pendingT = 0;
if (conn->result != NULL)
{
/* Read another tuple of a normal query response */
@@ -622,6 +638,7 @@ parseInput(PGconn *conn)
}
break;
case 'B': /* Binary data tuple */
+ pendingT = 0;
if (conn->result != NULL)
{
/* Read another tuple of a normal query response */
@@ -639,12 +656,15 @@ parseInput(PGconn *conn)
}
break;
case 'G': /* Start Copy In */
+ pendingT = 0;
conn->asyncStatus = PGASYNC_COPY_IN;
break;
case 'H': /* Start Copy Out */
+ pendingT = 0;
conn->asyncStatus = PGASYNC_COPY_OUT;
break;
default:
+ pendingT = 0;
sprintf(conn->errorMessage,
"unknown protocol character '%c' read from backend. "
"(The protocol character is the first character the "